﻿// -------------------------------------------------------------------------------------------------------------------------------
// <copyright file="TestAssign.cs" company="Exul">
//     Copyright (c) Exul. All rights reserved.
// </copyright>
// <author>
//     Exul
// </author>
// -------------------------------------------------------------------------------------------------------------------------------

namespace ExulLibrary.Mathematics.LinearAlgebra.Sequential.Tests.RMFlattenDenseMatrixTest
{
    #region Usings

    using System;

    using NUnit.Framework;

    #endregion

    /// <summary>
    ///     Test suite for
    ///     <see cref="RMFlattenDenseMatrixExtensions.Assign{T}(RMFlattenDenseMatrix{T},RMFlattenDenseMatrix{T})"/>.
    /// </summary>
    [TestFixture]
    [Category("ExulLibrary.Mathematics.LinearAlgebra.Sequential.RMFlattenDenseMatrixExtensions")]
    public sealed class TestAssign
    {
        /// <summary>
        ///     Tests the method when source and target have the same size.
        /// </summary>
        [Test]
        public void WhenSourceAndTargetHaveTheSameSize()
        {
            // Arrange
            var sourceData = new[]
                             {
                                 new object(), new object(), new object(),
                                 new object(), new object(), new object()
                             };
            var source = new RMFlattenDenseMatrix<object>(2, 3, sourceData);
            var targetData = new[]
                             {
                                 new object(), new object(), new object(),
                                 new object(), new object(), new object()
                             };
            var target = new RMFlattenDenseMatrix<object>(2, 3, targetData);

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0], Is.SameAs(source.Values[0]));
            Assert.That(target.Values[1], Is.SameAs(source.Values[1]));
            Assert.That(target.Values[2], Is.SameAs(source.Values[2]));
            Assert.That(target.Values[3], Is.SameAs(source.Values[3]));
            Assert.That(target.Values[4], Is.SameAs(source.Values[4]));
            Assert.That(target.Values[5], Is.SameAs(source.Values[5]));
        }

        /// <summary>
        ///     Tests the method when source has less count of rows than target.
        /// </summary>
        [Test]
        public void WhenSourceHasLessRowsCountThanTarget()
        {
            // Arrange
            var sourceData = new[]
                             {
                                 new object(), new object(), new object()
                             };
            var source = new RMFlattenDenseMatrix<object>(1, 3, sourceData);
            var targetData = new[]
                             {
                                 new object(), new object(), new object(),
                                 new object(), new object(), new object()
                             };
            var target = new RMFlattenDenseMatrix<object>(2, 3, targetData);

            var expectedResult = new[]
                                 {
                                     sourceData[0], sourceData[1], sourceData[2],
                                     targetData[3], targetData[4], targetData[5]
                                 };

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0], Is.SameAs(expectedResult[0]));
            Assert.That(target.Values[1], Is.SameAs(expectedResult[1]));
            Assert.That(target.Values[2], Is.SameAs(expectedResult[2]));
            Assert.That(target.Values[3], Is.SameAs(expectedResult[3]));
            Assert.That(target.Values[4], Is.SameAs(expectedResult[4]));
            Assert.That(target.Values[5], Is.SameAs(expectedResult[5]));
        }

        /// <summary>
        ///     Tests the method when source has greater count of rows than target.
        /// </summary>
        [Test]
        public void WhenSourceHasGreaterRowsCountThanTarget()
        {
            // Arrange
            var sourceData = new[]
                             {
                                 new object(), new object(), new object(),
                                 new object(), new object(), new object(),
                                 new object(), new object(), new object()
                             };
            var source = new RMFlattenDenseMatrix<object>(3, 3, sourceData);
            var targetData = new[]
                             {
                                 new object(), new object(), new object(),
                                 new object(), new object(), new object()
                             };
            var target = new RMFlattenDenseMatrix<object>(2, 3, targetData);

            var expectedResult = new[]
                                 {
                                     sourceData[0], sourceData[1], sourceData[2],
                                     sourceData[3], sourceData[4], sourceData[5]
                                 };

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0], Is.SameAs(expectedResult[0]));
            Assert.That(target.Values[1], Is.SameAs(expectedResult[1]));
            Assert.That(target.Values[2], Is.SameAs(expectedResult[2]));
            Assert.That(target.Values[3], Is.SameAs(expectedResult[3]));
            Assert.That(target.Values[4], Is.SameAs(expectedResult[4]));
            Assert.That(target.Values[5], Is.SameAs(expectedResult[5]));
        }

        /// <summary>
        ///     Tests the method when source has less count of columns than target.
        /// </summary>
        [Test]
        public void WhenSourceHasLessColumnsCountThanTarget()
        {
            // Arrange
            var sourceData = new[]
                             {
                                 new object(), new object(),
                                 new object(), new object()
                             };
            var source = new RMFlattenDenseMatrix<object>(2, 2, sourceData);
            var targetData = new[]
                             {
                                 new object(), new object(), new object(),
                                 new object(), new object(), new object()
                             };
            var target = new RMFlattenDenseMatrix<object>(2, 3, targetData);

            var expectedResult = new[]
                                 {
                                     sourceData[0], sourceData[1], targetData[2],
                                     sourceData[2], sourceData[3], targetData[5]
                                 };

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0], Is.SameAs(expectedResult[0]));
            Assert.That(target.Values[1], Is.SameAs(expectedResult[1]));
            Assert.That(target.Values[2], Is.SameAs(expectedResult[2]));
            Assert.That(target.Values[3], Is.SameAs(expectedResult[3]));
            Assert.That(target.Values[4], Is.SameAs(expectedResult[4]));
            Assert.That(target.Values[5], Is.SameAs(expectedResult[5]));
        }

        /// <summary>
        ///     Tests the method when source has greater count of columns than target.
        /// </summary>
        [Test]
        public void WhenSourceHasGreaterColumnsCountThanTarget()
        {
            // Arrange
            var sourceData = new[]
                             {
                                 new object(), new object(), new object(), new object(),
                                 new object(), new object(), new object(), new object()
                             };
            var source = new RMFlattenDenseMatrix<object>(2, 4, sourceData);
            var targetData = new[]
                             {
                                 new object(), new object(), new object(),
                                 new object(), new object(), new object()
                             };
            var target = new RMFlattenDenseMatrix<object>(2, 3, targetData);

            var expectedResult = new[]
                                 {
                                     sourceData[0], sourceData[1], sourceData[2],
                                     sourceData[4], sourceData[5], sourceData[6]
                                 };

            // Act
            target.Assign(source);

            // Assert
            Assert.That(target.Values, Is.Not.SameAs(source.Values));
            Assert.That(target.Values[0], Is.SameAs(expectedResult[0]));
            Assert.That(target.Values[1], Is.SameAs(expectedResult[1]));
            Assert.That(target.Values[2], Is.SameAs(expectedResult[2]));
            Assert.That(target.Values[3], Is.SameAs(expectedResult[3]));
            Assert.That(target.Values[4], Is.SameAs(expectedResult[4]));
            Assert.That(target.Values[5], Is.SameAs(expectedResult[5]));
        }

#if SAFE

        /// <summary>
        ///     Tests the method when source is <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenSourceIsNull()
        {
            // Arrange
            var target = new RMFlattenDenseMatrix<object>(2, 3);

            // Act and Assert
            Assert.That(
                () => target.Assign(null),
                Throws.TypeOf<ArgumentNullException>().With.Property("ParamName").EqualTo("source"));
        }

        /// <summary>
        ///     Tests the method when target is <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenTargetIsNull()
        {
            // Arrange
            var source = new RMFlattenDenseMatrix<object>(2, 3);

            // Act and Assert
            Assert.That(
                () => RMFlattenDenseMatrixExtensions.Assign(null, source),
                Throws.TypeOf<ArgumentNullException>().With.Property("ParamName").EqualTo("target"));
        }

#endif
    }
}